package com.pujiewang.gateway.handler;

import com.pujiewang.gateway.util.NetUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.resource.NoResourceFoundException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Optional;

@Component
@Order(-1) // 确保优先级高于默认的异常处理器
@Log4j2
public class CustomErrorWebExceptionHandler implements ErrorWebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        HttpStatus status = getHttpStatus(ex);
        String message = getErrorMessage(ex);
        String path = getRequestPath(exchange);

        // 设置响应状态码和内容类型
        exchange.getResponse().setStatusCode(status);
        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);

        // 构建自定义响应体
        log.error("请求异常, path: {}, status: {}, message: {}", path, status, message);
        return NetUtil.buildResponse(exchange, message, status);
    }

    /**
     * 根据异常类型获取 HTTP 状态码
     */
    private HttpStatus getHttpStatus(Throwable ex) {
        if (ex instanceof NoResourceFoundException) {
            return HttpStatus.NOT_FOUND;
        } else if (ex instanceof IllegalArgumentException) {
            return HttpStatus.BAD_REQUEST;
        } else if (ex instanceof UnsupportedOperationException) {
            return HttpStatus.METHOD_NOT_ALLOWED;
        } else {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }

    /**
     * 获取请求路径
     * @param exchange exchange
     * @return 请求路径字符串
     */
    private String getRequestPath(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        return Optional
                .ofNullable(request.getURI().getPath())
                .orElse("");
    }

    /**
     * 根据异常类型获取错误消息
     */
    private String getErrorMessage(Throwable ex) {
        if (ex instanceof NoResourceFoundException) {
            return "资源未找到";
        } else if (ex instanceof IllegalArgumentException) {
            return "请求参数无效";
        } else if (ex instanceof UnsupportedOperationException) {
            return "不支持的操作";
        } else {
            return "服务器内部异常";
        }
    }
}
